﻿using System;
using System.IO;
using System.Net;
using System.Text;
using System.Runtime.Serialization.Json;

namespace UpYourLife.Services.Google
{
    /// <summary>
    /// A set of methods for executing searches.
    /// </summary>
    public static class LocalSearchApi
    {
        private const string LocalSearchUrl = "http://ajax.googleapis.com/ajax/services/search/local?&key=ABQIAAAAjU0EJWnWPMv7oQ-jjS7dYxQ82LsCgTSsdpNEnBsExtoeJv4cdBSUkiLH6ntmAr_5O4EfjDwOa0oZBQ&v=1.0&sll=10.776414,106.682339&q={0}&start={1}&rsz=8";

        /// <summary>
        /// Executes a Google web search.
        /// </summary>
        /// <param name="searchPhrase">The phrase to base the search on.</param>
        /// <param name="start">The start index of the first result.</param>
        /// <param name="referer">The referring URL - required by Google's terms of service.</param>
        /// <returns>A set of search results.</returns>
        public static GoogleLocalResponseData SearchLocal(string searchPhrase, int start, string referer)
        {
            //* If a referer[sic] is not supplied then you're breaking Google's ToS
            if (string.IsNullOrEmpty(referer))
            {
                throw new ArgumentException("A referer must be supplied as part of a call to the Google AJAX API.");
            }
            string url = string.Format(LocalSearchUrl, searchPhrase, start);            
            string response = ExecuteHttpGet(url);
            return DeserialiseJson<GoogleLocalResponseData>(response);
        }

        /// <summary>
        /// Executes an Http Get request
        /// </summary>
        /// <param name="url">The address for the Http Request.</typeparam>
        /// <param name="headers">An optional set of headers to add to the request.</param>
        /// <returns>The request's response.</returns>
        private static string ExecuteHttpGet(string url)
        {
            using (WebClient client = new WebClient())
            {
                //if (headers != null)
                //{
                //    foreach (string header in headers)
                //    {
                //        client.Headers.Add(header);
                //    }
                //}

                using (Stream stream = client.OpenRead(url))
                {
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
        }

        /// <summary>
        /// Deserializes a Json string into am object.
        /// </summary>
        /// <typeparam name="T">The target type for Json deserialization.</typeparam>
        /// <param name="json">The Json string to deserialize.</param>
        /// <returns>The deserialized object</returns>
        private static T DeserialiseJson<T>(string json) where T : new()
        {
            if (!string.IsNullOrEmpty(json))
            {
                //byte[] respBytes = ASCIIEncoding.UTF8.GetBytes(json);
                byte[] respBytes = UTF8Encoding.UTF8.GetBytes(json);
                using (StreamReader reader = new StreamReader(new MemoryStream(respBytes)))
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
                    T returnObj = (T)serializer.ReadObject(reader.BaseStream);
                    return returnObj;
                }
            }
            else
            {
                return new T();
            }
        }

    }
}
